//
// Created by pzw on 24-3-25.
//

#include "SmartPtr.h"

template<typename Tp, typename... Args>
std::unique_ptr<Tp> SmartPtr::std_make_unique(Args &&...args) {
    return std::make_unique<Tp>(args...);
}

template<typename Tp, typename... Args>
std::unique_ptr<Tp> SmartPtr::std_constructor_unique(Args &&...args) {
    return std::unique_ptr<Tp>(new Tp(args...));
}

template<typename Tp, typename... Args>
std::shared_ptr<Tp> SmartPtr::std_make_shared(Args &&...args) {
    return std::make_shared<Tp>(args...);
}

template<typename Tp, typename... Args>
std::shared_ptr<Tp> SmartPtr::std_constructor_shared(Args &&...args) {
    return std::shared_ptr<Tp>(new Tp(args...));
}

template<typename Tp, typename... Args>
std::shared_ptr<Tp> SmartPtr::std_make_weak(Args &&...args) {
    return std::make_shared<Tp>(args...);
}

template<typename Tp, typename... Args>
std::shared_ptr<Tp> SmartPtr::std_constructor_weak(Args &&...args) {
    return std::shared_ptr<Tp>(new Tp(args...));
}


int SmartPtr_main() {
    {/* unique_ptr */
        std::unique_ptr<int> pInt = std::make_unique<int>(5);
        *pInt = 6;
        /* 注意: std::unique_ptr<int> == std::_MakeUniq<std::string>::__single_object
         * 内部直接用typedef unique_ptr<_Tp> __single_object定义的 */
        std::_MakeUniq<std::string>::__single_object pText = std::make_unique<std::string>("pText");
        *pText = "6";
        const std::unique_ptr<std::string> &pText2 = SmartPtr::std_make_unique<std::string>("pText2");
        const std::unique_ptr<std::string> &pText3 = SmartPtr::std_constructor_unique<std::string>("pText3");
        std::cout << "SmartPtr_main: pInt = " << *pInt << ", pText = " + *pText
                  << ", pText2 = " << *pText2 << ", pText3 = " << *pText3 << std::endl;
    }

    {/* shared_ptr */
        const std::shared_ptr<int> &spInt = SmartPtr::std_make_shared<int>(7);
        const std::shared_ptr<std::string> &spText
                = SmartPtr::std_constructor_shared<std::string>("shared_ptr");
        std::cout << "SmartPtr_main: spInt = " << *spInt << ", spText = " << *spText << std::endl;
    }

    {/* weak_ptr：注意以下代码，全都是固定用法，连格式，作用域都是固定的 */
        std::weak_ptr<int> wpInt;
        std::weak_ptr<std::string> wpText;
        {
            const std::shared_ptr<int> &std_make_weak = SmartPtr::std_make_weak<int>(8);
            const std::shared_ptr<std::string> &std_constructor_weak
                    = SmartPtr::std_constructor_weak<std::string>("wpText by shared");
            wpInt = std_make_weak;
            wpText = std_constructor_weak;
            const std::shared_ptr<int> &ptr = wpInt.lock();
            if (ptr != nullptr && wpText.lock() != nullptr) {
                std::cout << "SmartPtr_main: wpInt = " << *ptr << ", wpText = " << *(wpText.lock()) << std::endl;
            } else {
                std::cout << "SmartPtr_main: wpInt = " << (ptr == nullptr)
                          << ", wpText = " << (wpText.lock() == nullptr) << std::endl;
            }
        }
#if 1   // 因为weak_ptr只能使用一次，我么基本用不到它
        std::shared_ptr<int> wpInt2 = wpInt.lock();
        auto wpText2 = wpText.lock();
        if (wpInt2 != nullptr && wpText2 != nullptr) {
            std::cout << "SmartPtr_main: wpInt2 = " << *wpInt2 << ", wpText2 = " << *wpText2 << std::endl;
        } else {
            std::cout << "SmartPtr_main: Using weak_ptr again is nullptr" << std::endl;
        }
#endif
    }

    return 0;
}